/**
 * 菜单列表 扁平
 * @param {String} name 菜单唯一标识，对应页面组件name, 可用作KeepAlive缓存标识
 * @param {String} parentName 所属父级菜单name，空为根节点
 * @param {String} path 菜单访问路径，需要添加前缀斜杠/
 * @param {String} component 视图文件路径，需要添加前缀斜杠/，注意@/views及.vue后缀需省略，例home页为：/home/index
 * @param {String} redirect 菜单重定向地址，需要添加前缀斜杠/
 * @param {Object} meta 菜单元信息
 * @property {String} meta.title 菜单标题
 * @property {String} meta.icon 菜单图标
 * @property {String} meta.type 菜单类型：directory目录 | menu菜单 | button按钮
 * @property {String} meta.authCode 菜单权限标识，例：sys:menu:list
 * @property {String} meta.link 菜单外链地址，为空时为非外链
 * @property {String} meta.highlight 需要高亮的菜单name，常用于详情页使其上级高亮，默认为空使自己高亮
 * @property {Number} meta.sort 菜单排序
 * @property {Boolean} meta.blank 是否新标签页打开
 * @property {Boolean} meta.hide 是否隐藏菜单，仅隐藏不显示，但该菜单依然会注册在菜单表中，详情页通常需要隐藏自己然后高亮上级菜单
 * @property {Boolean} meta.disabled 是否禁用菜单，不注册该菜单
 * @property {Boolean} meta.affix 是否固定在标签栏中，通常固定首页
 * @property {Boolean} meta.layouts 是否使用布局，默认true，不使用布局的页面为纯净的全屏页
 * @property {Boolean} meta.keepAlive 是否缓存当前菜单，默认true
 */
const menuFlat = [
  // 系统管理
  {
    name: 'system',
    parentName: '',
    path: '/system',
    component: '',
    redirect: '',
    meta: {
      title: '系统管理',
      icon: 'sv-icon-all',
      type: 'directory',
      authCode: '',
      link: '',
      highlight: '',
      sort: 10,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'user',
    parentName: 'system',
    path: '/system/user',
    component: '/system/user/index',
    redirect: '',
    meta: {
      title: '用户管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 1,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'role',
    parentName: 'system',
    path: '/system/role',
    component: '/system/role/index',
    redirect: '',
    meta: {
      title: '角色管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 2,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'department',
    parentName: 'system',
    path: '/system/department',
    component: '/system/department/index',
    redirect: '',
    meta: {
      title: '部门管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 3,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'menu',
    parentName: 'system',
    path: '/system/menu',
    component: '/system/menu/index',
    redirect: '',
    meta: {
      title: '菜单管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 4,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'dict',
    parentName: 'system',
    path: '/system/dict',
    component: '/system/dict/index',
    redirect: '',
    meta: {
      title: '字典管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 5,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'parameter',
    parentName: 'system',
    path: '/system/parameter',
    component: '/system/parameter/index',
    redirect: '',
    meta: {
      title: '参数管理',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 6,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'log',
    parentName: 'system',
    path: '/system/log',
    component: '',
    redirect: '/system/log/loginLog',
    meta: {
      title: '日志管理',
      icon: 'sv-icon-all',
      type: 'directory',
      authCode: '',
      link: '',
      highlight: '',
      sort: 7,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'loginLog',
    parentName: 'log',
    path: '/system/log/loginLog',
    component: '/system/log/loginLog/index',
    redirect: '',
    meta: {
      title: '登录日志',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 1,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'operationLog',
    parentName: 'log',
    path: '/system/log/operationLog',
    component: '/system/log/operationLog/index',
    redirect: '',
    meta: {
      title: '操作日志',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 2,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },

  // 系统工具
  {
    name: 'tool',
    parentName: '',
    path: '/tool',
    component: '',
    redirect: '/tool/gen',
    meta: {
      title: '系统工具',
      icon: 'sv-icon-all',
      type: 'directory',
      authCode: '',
      link: '',
      highlight: '',
      sort: 20,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'gen',
    parentName: 'tool',
    path: '/tool/gen',
    component: '/tool/gen/index',
    redirect: '',
    meta: {
      title: '代码生成',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 1,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'iconview',
    parentName: 'tool',
    path: '/tool/iconview',
    component: '/tool/iconview/index',
    redirect: '',
    meta: {
      title: '图标预览',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 2,
      blank: false,
      hide: false,
      disabled: false,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
  {
    name: 'swagger',
    parentName: 'tool',
    path: '/tool/swagger',
    component: '/tool/swagger/index',
    redirect: '',
    meta: {
      title: '接口文档',
      icon: 'sv-icon-all',
      type: 'menu',
      authCode: '',
      link: '',
      highlight: '',
      sort: 3,
      blank: false,
      hide: false,
      disabled: true,
      affix: false,
      layouts: true,
      keepAlive: true,
    },
  },
]

const menuTree = buildMenuTree(menuFlat)

const routeFlat = buildRouteFlat(menuFlat)

const routeTree = buildMenuTree(routeFlat)

/**
 * 菜单树构建
 * @param {Array} flatMenuList - 扁平菜单数组
 * @param {Object} options - 配置选项
 * @property {boolean} options.ignoreOrphanNode - 是否忽略孤儿节点：true舍去(默认) | false作为根节点
 * @property {string} options.rootParentName - 根节点的父节点标识，默认空字符串
 * @property {string} options.idKey - 节点ID字段名，默认name
 * @property {string} options.parentIdKey - 父节点ID字段名，默认parentName
 * @property {string} options.childrenKey - 子节点字段名，默认children
 * @property {string} options.sortKey - 排序字段路径，默认meta.sort
 * @property {boolean} options.enableSorting - 是否启用排序，默认true
 * @returns {Array} 树状菜单结构
 */
function buildMenuTree(flatMenuList, options = {}) {
  const {
    ignoreOrphanNode = true,
    rootParentName = '',
    idKey = 'name',
    parentIdKey = 'parentName',
    childrenKey = 'children',
    sortKey = 'meta.sort',
    enableSorting = true,
  } = options

  // 循环引用检测
  const visited = new Set()

  // 构建节点映射
  const nodeMap = new Map()
  const missingParents = new Set()

  flatMenuList.forEach((item) => {
    const nodeId = item[idKey]
    if (visited.has(nodeId)) {
      console.warn(`mock ===> 检测到重复的节点ID: ${nodeId}`)
      return
    }
    visited.add(nodeId)

    nodeMap.set(nodeId, {
      ...item,
      [childrenKey]: [],
    })
  })

  // 构建树结构
  const tree = []

  flatMenuList.forEach((item) => {
    const nodeId = item[idKey]
    const parentId = item[parentIdKey]
    const currentNode = nodeMap.get(nodeId)

    if (!parentId || parentId === rootParentName) {
      tree.push(currentNode)
    } else {
      const parentNode = nodeMap.get(parentId)
      if (parentNode) {
        parentNode[childrenKey].push(currentNode)
      } else {
        if (ignoreOrphanNode) {
          console.warn(`mock ===> 孤儿节点 ${nodeId} 已被舍去：其父节点 ${parentId} 不存在`)
        } else {
          missingParents.add(parentId)
          // 将孤儿节点作为根节点处理
          tree.push(currentNode)
        }
      }
    }
  })

  // 输出警告信息
  if (missingParents.size > 0) {
    console.warn(`mock ===> 未找到以下父节点: ${Array.from(missingParents).join(', ')}`)
  }

  // 辅助函数：获取嵌套对象值
  const getNestedValue = (obj, path) => {
    return path.split('.').reduce((current, key) => {
      return current && current[key] !== undefined ? current[key] : undefined
    }, obj)
  }

  // 递归排序函数
  const sortTree = (nodes) => {
    if (!enableSorting || !nodes.length) return nodes

    return nodes
      .map((node) => {
        return {
          ...node,
          [childrenKey]: sortTree(node[childrenKey]),
        }
      })
      .sort((a, b) => {
        const sortA = getNestedValue(a, sortKey)
        const sortB = getNestedValue(b, sortKey)
        return (sortA || 0) - (sortB || 0)
      })
  }

  return sortTree(tree)
}

/**
 * 扁平路由列表
 * @param {Array} flatMenuList - 扁平菜单数组
 * @returns
 */
function buildRouteFlat(flatMenuList) {
  const filterRoutes = flatMenuList.filter((item) => {
    // TODO 后续还需追加对authCode的权限判断
    return !item.meta?.disabled && item.meta.type !== 'button'
  })
  return filterRoutes
}

// API 模拟接口
export const apiMenu = [
  // 扁平菜单列表，需要鉴权
  {
    url: '/api/menu/list',
    method: 'post',
    response: (request) => {
      // 获取请求头携带的 token
      const authorization = request.headers['authorization']
      const token = authorization?.split(' ')[1] // Bearer token 截取

      // 失败
      if (!token) {
        return {
          code: 401,
          data: null,
          msg: '鉴权失败，请重新登录',
        }
      }

      // 成功
      return {
        code: 200,
        data: menuFlat,
        msg: '请求成功',
      }
    },
  },
  // 菜单树，需要鉴权
  {
    url: '/api/menu/tree',
    method: 'post',
    response: (request) => {
      // 获取请求头携带的 token
      const authorization = request.headers['authorization']
      const token = authorization?.split(' ')[1] // Bearer token 截取

      // 失败
      if (!token) {
        return {
          code: 401,
          data: null,
          msg: '鉴权失败，请重新登录',
        }
      }

      // 成功
      return {
        code: 200,
        data: menuTree,
        msg: '请求成功',
      }
    },
  },

  // 扁平路由列表，需要鉴权
  {
    url: '/api/route/list',
    method: 'get',
    response: (request) => {
      // 获取请求头携带的 token
      const authorization = request.headers['authorization']
      const token = authorization?.split(' ')[1] // Bearer token 截取

      // 失败
      if (!token) {
        return {
          code: 401,
          data: null,
          msg: '鉴权失败，请重新登录',
        }
      }

      // 成功
      return {
        code: 200,
        data: routeFlat,
        msg: '请求成功',
      }
    },
  },
  // 路由树，需要鉴权
  {
    url: '/api/route/tree',
    method: 'get',
    response: (request) => {
      // 获取请求头携带的 token
      const authorization = request.headers['authorization']
      const token = authorization?.split(' ')[1] // Bearer token 截取

      // 失败
      if (!token) {
        return {
          code: 401,
          data: null,
          msg: '鉴权失败，请重新登录',
        }
      }

      // 成功
      return {
        code: 200,
        data: routeTree,
        msg: '请求成功',
      }
    },
  },
]
